#include<stdio.h>
#include<unistd.h>
#include<string.h>

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>


//--------Part VI验证C语言库 封装的FILE结构体-----------
//stdin/stdout/stderr是(c封装的)三个FILE类型结构体 (OS只有文件概念)
//必定有fd 且对应0,1,2,一定是键盘文件，显示器文件，显示器文件
int main()
{
    close(1);//如果把此进程显示器文件关闭，printf没有结果
    printf("stdin->fd: %d\n",stdin->_fileno);//既然是结构体，我们就能->访问
    printf("stdout->fd: %d\n",stdout->_fileno);
    int n = printf("stderr->fd: %d\n",stderr->_fileno);
    
    fprintf(stdout,"stdout:rintf ret: %d\n",n);//打不出来
    fprintf(stderr,"stderr:printf ret: %d\n",n);//printf以为它自己写成功了
    //所以stderr和stdout是两个不同文件描述符描述的

    return 0;
}



//--------Part V 验证fd下标0,1,2对应stdin,stdout,stderr三个默认打开文件---

//int main()
//{
//    const char* msg = "hello stdout\n";
//    write(1,msg,strlen(msg));//向显示器文件写入
//    write(2,msg,strlen(msg));//向显示器文件写入-标准错误
//   
//    char buffer[1024];
//    size_t size = read(0,buffer,sizeof(buffer));//从键盘文件读数据
//
//    //但因为我们是用C语言输出的，c语言认为字符串应该以'\0'结尾
//    //但我们从键盘读入的，用系统调用接口得到的字符串->只是字符
//    buffer[size] = '\0';//read返回读取字符长度
//
//    printf("echo: %s\n",buffer);//打印读入到buffer的数据
//    
//
//    return 0;
//}


//--------Part IV 系统调用 open---------
//int main()
//{
//    umask(0);//修改程序的掩码，不影响整个系统，影响整个进程
//
//    //int fd = open("log.txt",O_WRONLY|O_CREAT);//O_WRONLY只是写入，如果不存在会失败，需要加上creat
//    //int fd = open("log.txt",O_WRONLY|O_CREAT,0666);
//    //int fd = open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);//清空
//    int fd = open("log.txt",O_WRONLY|O_CREAT|O_APPEND,0666);//追加
//    if(fd<0){
//        printf("openfile error\n");
//        return 1;
//    }
//   
//   printf("fd: %d\n",fd);//fd 是结构体中指针数组的下标：让进程:找到文件
//    //const  char* message = "file system call\n";
//    const  char* message = "fx is a cat \n";//只写入，不会像"w"那样清空
//    write(fd,message,strlen(message));
//
//    return 0;
//}



//---------Part III比特位级别的标志位-----------
//#define ONE (1<<0)//1
//#define TWO (1<<1)//2
//#define THREE (1<<2)//4
//#define FOUR (1<<3)//8
//
//void show(int flags)
//{
//    if(flags & ONE) printf("hello 1\n");
//    if(flags & TWO) printf("hello 2\n");
//    if(flags & THREE) printf("hello 3\n");
//    if(flags & FOUR) printf("hello 4\n");
//}
//
//int main()
//{
//    show(ONE);
//    show(TWO);
//    show(ONE|TWO);
//    show(TWO|FOUR);
//    show(ONE|TWO|THREE|FOUR);
//    return 0;
//}



//int main()
//{
//    //chdir("/home/fx");
//    //改变cwd：让文件在别的路径下被创建
//    //FILE *fp = fopen("log.txt","w");//"w"方式打卡:就要清空文件，不管是否写入
//    FILE *fp = fopen("log.txt","a");///追加
//
//    if(fp == NULL) 
//    {
//        perror("fopen");
//        return 1;
//    }
//        
//    const char* message = "hello xh\n";
//    //fwrite(message,strlen(message)+1,1,fp);
////    fwrite(message,strlen(message),1,fp);//不要+1,为什么？字符串以\0结尾是c语言的规定，与文件没有关系-->被java/python...读取，和c语言没有关系，把内容写入就够了
//
//    //-------------Part II--------------
//    //fwrite(message,strlen(message),1,stdout);//向显示器输出
//    //fprintf(fp,"%s:%d",message,1234) ;//指定文件流
//    fprintf(stdout,"%s:%d",message,1234) ;//文件流为显示器(显示器和其他文件流没有区别)
//
//
//    fclose(fp);
//
//    
//    return 0;
//}
